package com.navinfo.tripanalysis.service;

import com.navinfo.tripanalysis.common.util.CommonUtils;
import com.navinfo.tripanalysis.service.impl.*;
import com.navinfo.tripanalysis.util.BigDataUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Service工厂类
 * @author 沈东生
 */
public class ServiceFactory implements Serializable {
    private Properties config;

    public ServiceFactory(Properties config) {
        this.config = config;
    }

    /**
     * 创建加载车辆信息的服务
     */
    public AbstractLoadVehicleInfoService createLoadVehicleInfoService() {
        AbstractLoadVehicleInfoService service = new LoadVehicleInfoServiceImpl_DF();
        service.setDriver(config.getProperty("vehicleinfo.jdbc.driver"));
        service.setUrl(config.getProperty("vehicleinfo.jdbc.url"));
        service.setUser(config.getProperty("vehicleinfo.jdbc.username"));
        service.setPass(config.getProperty("vehicleinfo.jdbc.password"));
        service.setVehicle_hql(config.getProperty("vehicleinfo.vehicle.hql"));
        return service;
    }
    /**
     * 创建加载尿素信息的服务
     */
    public AbstractLoadUreaInfoService createLoadUreaInfoService() {
        AbstractLoadUreaInfoService service = new LoadUreaInfoServiceImpl_DF();
        service.setDriver(config.getProperty("vehicleinfo.jdbc.driver"));
        service.setUrl(config.getProperty("vehicleinfo.jdbc.url"));
        service.setUser(config.getProperty("vehicleinfo.jdbc.username"));
        service.setPass(config.getProperty("vehicleinfo.jdbc.password"));
        return service;
    }

    /**
     * 创建大数据分批处理服务
     */
    public DataBatchService createDataBatchService() {
        String type = config.getProperty("load.data.batch.type");
        if (StringUtils.equals(type, "bigdata")) {
            DataBatchServiceBigDataImpl service = new DataBatchServiceBigDataImpl();
            service.setBatchSize(Integer.parseInt(config.getProperty("load.data.batch.bigdata.size")));
            return service;
        }
        throw new RuntimeException("不支持DataBatchService类型:" + type);
    }

    /**
     * 创建加载0f37服务（可hdfs、excel、hive）
     */
    public Load0F37DataService createLoad0F37DataService() {
        String type = config.getProperty("load.data.0f37.type");
        boolean supportProtocolType = Boolean.parseBoolean(config.getProperty("load.data.0f37.supportProtocoltype"));
        if (StringUtils.equals(type, "hdfs")) {
            Load0F37DataServiceHdfsImpl service = new Load0F37DataServiceHdfsImpl();
            service.setBasePath(config.getProperty("load.data.0f37.hdfs.basepath"));
            service.setSupportProtocolType(supportProtocolType);
            return service;
        } else if (StringUtils.equals(type, "hive")) {
            Load0F37DataServiceHiveImpl service = new Load0F37DataServiceHiveImpl();
            service.setDbName(config.getProperty("load.data.0f37.hive.dbname"));
            service.setTableName(config.getProperty("load.data.0f37.hive.tablename"));
            service.setSupportProtocolType(supportProtocolType);
            return service;
        } else if (StringUtils.equals(type, "excel")) {
            Load0F37DataServiceExcelImpl service = new Load0F37DataServiceExcelImpl();
            service.setPath(config.getProperty("tools.point.excel.basepath"));
            return service;
        }
        throw new RuntimeException("不支持Load0F37DataService类型:" + type);
    }

    /**
     * 创建加载0200服务（可hdfs、excel、hive）
     */
    public Load0200DataService createLoad0200DataService() {
        String type = config.getProperty("load.data.0200.type");
        //是否支持serialNumber字段
        boolean supportSerialNumber = Boolean.parseBoolean(config.getProperty("load.data.0200.supportSerialNumber"));
        if (StringUtils.equals(type, "hdfs")) {
            Load0200DataServiceHdfsImpl service = new Load0200DataServiceHdfsImpl();
            service.setBasePath(config.getProperty("load.data.0200.hdfs.basepath"));
            service.setSupportSerialNumber(supportSerialNumber);
            return service;
        } else if (StringUtils.equals(type, "hive")) {
            Load0200DataServiceHiveImpl service = new Load0200DataServiceHiveImpl();
            service.setDbName(config.getProperty("load.data.0200.hive.dbname"));
            service.setTableName(config.getProperty("load.data.0200.hive.tablename"));
            service.setSupportSerialNumber(supportSerialNumber);
            return service;
        } else if (StringUtils.equals(type, "excel")) {
            Load0200DataServiceExcelImpl service = new Load0200DataServiceExcelImpl();
            service.setPath(config.getProperty("tools.point.excel.basepath"));
            return service;
        }
        throw new RuntimeException("不支持Load0F37DataService类型:" + type);
    }

    /**
     * 创建位置点重分区、分区内排序服务
     */
    public PointsSortGroupService createPointsSortGroupService() {
        String type = config.getProperty("pointsSortGroup.type");
        if (StringUtils.equals("type1", type)) {
            PointsSortGroupServiceImpl1 service = new PointsSortGroupServiceImpl1();
            if(StringUtils.isNotEmpty(config.getProperty("pointsSortGroup.removeDuplicate"))){
                service.setRemoveDuplicate(Boolean.valueOf(config.getProperty("pointsSortGroup.removeDuplicate")));
            }
            return service;
        } else if (StringUtils.equals("type2", type)) {
            PointsSortGroupServiceImpl2 service = new PointsSortGroupServiceImpl2();
            String parallel = config.getProperty("pointsSortGroup.type2.parallel");
            if (StringUtils.isNotEmpty(parallel)) {
                service.setParallel(Integer.parseInt(config.getProperty(parallel)));
            }
            return service;
        } else {
            throw new RuntimeException("PointsSortGroupService:" + type);
        }
    }

    /**
     * 创建行程切分服务
     * @return
     */
    public PreTripInfoService createPreTripInfoService(){
        return new PreTripInfoServiceImpl2();
    }

    /**
     * 创建0F37算法链服务
     * @param algorithmConfig
     * @return
     */
    public AlgorithmChainService0F37 createAlgorithmChainService0f37(Map algorithmConfig) {
        return new AlgorithmChainService0F37(algorithmConfig);
    }

    /**
     * 创建0200算法链服务
     * @param algorithmConfig
     * @return
     */
    public AlgorithmChainService0200 createAlgorithmChainService0200(Map algorithmConfig) {
        return new AlgorithmChainService0200(algorithmConfig);
    }


    /**
     * 创建行程数据落盘服务，可mongo、bigdata
     */
    public List<SaveTripService> createSaveTripServices() {
        return createSaveTripServices("");
    }
    public List<SaveTripService> createSaveTripServices(String prefix) {
        List<SaveTripService> services = new ArrayList<>();
        List<String> types = CommonUtils.splitStr(config.getProperty(prefix+"save.trip.types"), ",");
        for (String type : types) {
            if (StringUtils.equals("mongo", type)) {
                SaveTripServiceMongoImpl service = new SaveTripServiceMongoImpl();
                service.setCollectionNamePrefix(config.getProperty(prefix+"save.trip.mongo.collectionNamePrefix"));
                service.setConfig(config);
                services.add(service);
            } else if (StringUtils.equals("bigdata", type)) {
                SaveTripServiceBigDataImpl service = new SaveTripServiceBigDataImpl();
                setSaveDataBigDataService(service, "save.trip");
                services.add(service);
            } else {
                throw new RuntimeException("不支持SaveTripService类型:" + type);
            }
        }
        return services;
    }

    /**
     * 创建行程扩展数据落盘服务，可mongo、bigdata
     */
    public List<SaveTripService> createSaveTripExtendServices() {
        return createSaveTripExtendServices("");
    }
    public List<SaveTripService> createSaveTripExtendServices(String prefix) {
        List<SaveTripService> services = new ArrayList<>();
        List<String> types = CommonUtils.splitStr(config.getProperty(prefix + "save.trip.types"), ",");
        for (String type : types) {
            if (StringUtils.equals("mongo", type)) {
                SaveTripExtendServiceMongoImpl service = new SaveTripExtendServiceMongoImpl();
                service.setCollectionNamePrefix(config.getProperty(prefix + "save.trip.extend.mongo.collectionNamePrefix"));
                service.setConfig(config);
                services.add(service);
            } else if (StringUtils.equals("bigdata", type)) {
                SaveTripExtendServiceBigDataImpl service = new SaveTripExtendServiceBigDataImpl();
                setSaveDataBigDataService(service, "save.trip");
                service.setHiveTableName(config.getProperty("save.trip.extend.bigdata.hiveTableName"));
                services.add(service);
            } else {
                throw new RuntimeException("不支持SaveTripService类型:" + type);
            }
        }
        return services;
    }

    /**
     * 创建事件数据落盘服务，可mongo、hbase、bigdata
     */
    public List<SaveEventService> createSaveEventServices() {
        return createSaveEventServices("");
    }
    public List<SaveEventService> createSaveEventServices(String prefix) {
        List<SaveEventService> services = new ArrayList<>();
        List<String> types = CommonUtils.splitStr(config.getProperty(prefix+"save.event.types"), ",");

        for (String type : types) {
            if (StringUtils.equals("mongo", type)) {
                SaveEventServiceMongoImpl service = new SaveEventServiceMongoImpl();
                service.setCollectionNamePrefix(config.getProperty(prefix+"save.event.mongo.collectionNamePrefix"));
                service.setConfig(config);
                services.add(service);
            } else if (StringUtils.equals("hbase", type)) {
                SaveEventServiceHBaseImpl service = new SaveEventServiceHBaseImpl();
                service.setTableName(config.getProperty(prefix+"save.event.hbase.tableName"));
                service.setQuorum(config.getProperty("hbase.zookeeper.quorum"));
                service.setPort(config.getProperty("hbase.zookeeper.property.clientPort"));
                service.setParent(config.getProperty("zookeeper.znode.parent"));
                String saveType = config.getProperty(prefix+"save.event.hbase.saveType");
                if (StringUtils.isEmpty(saveType)) {
                    saveType = SaveEventServiceHBaseImpl.SAVE_TYPE_2;
                }
                service.setSaveType(saveType);
                services.add(service);
            } else if (StringUtils.equals("bigdata", type)) {
                SaveEventServiceBigDataImpl service = new SaveEventServiceBigDataImpl();
                setSaveDataBigDataService(service, "save.event");
                services.add(service);
            } else {
                throw new RuntimeException("不支持SaveTripService类型:" + type);
            }
        }
        return services;
    }

    /**
     * 创建中间数据落盘服务
     */
    public DrivingDataService createDrivingDataService() {
        String type = config.getProperty("save.drivingdata.type");
        if (StringUtils.equals("bigdata", type)) {
            DrivingDataServiceImpl drivingDataService = new DrivingDataServiceImpl();
            setSaveDataBigDataService(drivingDataService, "save.drivingdata");
            return drivingDataService;
        }
        return null;
    }

    /**
     * 创建公共轨迹协议落盘服务
     */
    public SavePointService createSavePointService() {
        String type = config.getProperty("save.point.bigdata.type");
        if (StringUtils.equals("hive", type)) {
            SavePointServiceImpl savePointService = new SavePointServiceImpl();
            setSaveDataBigDataService(savePointService, "save.point");
            return savePointService;
        }
        return null;
    }


    private void setSaveDataBigDataService(AbstractSaveDataBigDataService service, String keyPrefix) {
        String coalesceType = config.getProperty(keyPrefix + ".bigdata.coalesceType");
        if (StringUtils.isNotEmpty(coalesceType)) {
            service.setCoalesceType(BigDataUtils.CoalesceType.valueOf(coalesceType));
        }
        String coalesceNumber = config.getProperty(keyPrefix + ".bigdata.coalesceNumber");
        if (StringUtils.isNotEmpty(coalesceNumber)) {
            service.setCoalesceNumber(Integer.valueOf(coalesceNumber));
        }
        
        service.setSaveType(config.getProperty(keyPrefix + ".bigdata.type"));
        service.setHiveDbName(config.getProperty(keyPrefix + ".bigdata.hiveDbName"));
        service.setHiveTableName(config.getProperty(keyPrefix + ".bigdata.hiveTableName"));
        service.setHdfsBasePath(config.getProperty(keyPrefix + ".bigdata.hdfsBasePath"));
    }

    /**
     * 创建加载瓦片信息服务
     */
    public LoadTileService createLoadTileService() {
        LoadTileServiceImpl service = new LoadTileServiceImpl();
        service.setHDFSPath(config.getProperty("load.data.tile.hdfspath"));
        return service;
    }

    /**
     * 创建读取行程服务
     */
    public LoadTripDataService createLoadTripService(){
        LoadTripServiceHiveImpl service=new LoadTripServiceHiveImpl();
        service.setDbname(config.getProperty("load.data.trip.hive.dbname"));
        service.setTablename(config.getProperty("load.data.trip.hive.tablename"));
        return service;
    }

    /**
     * 创建读取事件数据服务
     */
    public LoadEventDataService createLoadEventService(){
        LoadEventServiceHiveImpl service=new LoadEventServiceHiveImpl();
        service.setDbname(config.getProperty("load.data.event.hive.dbname"));
        service.setTablename(config.getProperty("load.data.event.hive.tablename"));
        return service;
    }

    /**
     * 创建读取异常公共轨迹协议点数据服务
     */

    public LoadAbnormalProtocolPointDataService createLoadAbnormalProtocolPointService(){

        LoadAbnormalProtocolPointServiceImpl service = new LoadAbnormalProtocolPointServiceImpl();
        service.setDBname(config.getProperty("load.data.protocol.hive.dbname"));
        service.setTablename(config.getProperty("load.data.protocol.hive.tablename"));
        return service;
    }

    /**
     * 创建读取异常行程数据
     */

    public LoadAbnormalTripStatictisDataService createLoadAbnormalTripStatictisService(){

        LoadAbnormalTripStatictisServiceImpl service = new LoadAbnormalTripStatictisServiceImpl();
        service.setS_DBname(config.getProperty("load.data.trip.hive.Sdbname"));
        service.setS_Tablename(config.getProperty("lload.data.trip.hive.Stablename"));
        service.setT_DBname("load.data.trip.hive.Tdbname");
        service.setT_Tablename("load.data.trip.hive.Ttablename");
        service.setTemptable("load.data.trip.hive.Temptablename");
        return service;

    }

}
